using Microsoft.AspNetCore.Http;
using System.Security.Claims;
using UniversalAdmin.Application.DTOs;
using UniversalAdmin.Application.Services;

namespace UniversalAdmin.Api.Middleware;

public class PermissionMiddleware
{
    private readonly RequestDelegate _next;

    public PermissionMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        // 跳过不需要权限检查的路径
        if (ShouldSkipPermissionCheck(context.Request.Path))
        {
            // 对于跳过的路径，仍然需要检查认证（如果控制器有[Authorize]属性）
            await _next(context);
            return;
        }

        // 检查用户是否已认证
        if (!context.User.Identity?.IsAuthenticated ?? true)
        {
            context.Response.StatusCode = 401;
            await context.Response.WriteAsJsonAsync(new { message = "未认证" });
            return;
        }

        // 检查用户是否有权限访问当前路径
        var hasPermission = await CheckUserPermissionAsync(context);
        if (!hasPermission)
        {
            context.Response.StatusCode = 403;
            await context.Response.WriteAsJsonAsync(new { message = "权限不足" });
            return;
        }

        await _next(context);
    }

    private bool ShouldSkipPermissionCheck(PathString path)
        {
            var pathValue = path.Value?.ToLower();
            
            // 跳过权限检查的路径列表
            var skipPaths = new[]
            {
                "/api/v1/auth",
                "/api/v1/document",
                "/api/v1/chat",
                "/swagger",
                "/api/v1/systemconfig",
                "/api/v1/operationlog",
                "/api/v1/menu",
                "/api/v1/role",
                "/api/v1/permission",
                "/api/v1/user",
                "/api/v1/personal",
                "/api/v1/article",
                "/api/v1/articlecategory"
            };

            return skipPaths.Any(skipPath => pathValue?.StartsWith(skipPath) == true);
        }

    private async Task<bool> CheckUserPermissionAsync(HttpContext context)
    {
        try
        {
            // 从服务提供器获取作用域服务
            var menuService = context.RequestServices.GetRequiredService<IMenuService>();
            var userService = context.RequestServices.GetRequiredService<IUserService>();

            // 获取当前用户ID - 尝试多种声明类型
            var userIdClaim = context.User.FindFirst(ClaimTypes.NameIdentifier) ??
                             context.User.FindFirst("sub") ??
                             context.User.FindFirst(ClaimTypes.Name);
            
            if (userIdClaim == null || !Guid.TryParse(userIdClaim.Value, out var userId))
            {
                // 如果无法获取用户ID，记录警告并允许访问（让控制器层的[Authorize]处理）
                var logger = context.RequestServices.GetRequiredService<ILogger<PermissionMiddleware>>();
                logger.LogWarning("PermissionMiddleware: 无法获取用户ID，跳过权限检查");
                return true;
            }

            // 获取用户信息
            var user = await userService.GetUserByIdAsync(userId);
            if (user == null) 
            {
                var logger = context.RequestServices.GetRequiredService<ILogger<PermissionMiddleware>>();
                logger.LogWarning("PermissionMiddleware: 用户不存在，跳过权限检查");
                return true;
            }

            // 超级管理员拥有所有权限
            if (user.Roles.Any(r => r.Name == "SuperAdmin"))
                return true;

            // 获取当前请求的路径
            var requestPath = context.Request.Path.Value?.ToLower();
            if (string.IsNullOrEmpty(requestPath)) return true;

            // 获取所有菜单
            var allMenus = await menuService.GetAllMenusAsync();

            // 查找匹配的菜单
            var matchingMenu = allMenus.FirstOrDefault(m =>
                requestPath.Contains(m.Path.ToLower()) ||
                requestPath.EndsWith(m.Path.ToLower()));

            if (matchingMenu == null) return true; // 如果没有匹配的菜单，允许访问

            // 检查用户是否有该菜单的权限
            var userRoles = user.Roles.Select(r => r.Id).ToList();
            var roleMenus = await menuService.GetMenusByRoleAsync(userRoles.First()); // 获取角色的菜单
            var hasMenuPermission = roleMenus.Any(m => m.Id == matchingMenu.Id); // 检查是否有该菜单权限

            return hasMenuPermission;
        }
        catch (Exception ex)
        {
            // 发生异常时，记录错误并允许访问（避免因权限系统错误导致所有接口不可用）
            var logger = context.RequestServices.GetRequiredService<ILogger<PermissionMiddleware>>();
            logger.LogError(ex, "PermissionMiddleware: 权限检查发生异常");
            return true;
        }
    }
}